package com.flyco.modules.oms.controller;

import java.io.IOException;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.flyco.common.constant.StockConstant;
import com.flyco.common.util.IdUtil;
import com.flyco.common.util.RedisUtil;
import com.flyco.modules.oms.entity.*;
import com.flyco.modules.oms.vo.OmsOrderPage;
import com.flyco.modules.pms.service.IPmsProductService;
import com.flyco.modules.pms.vo.PmsProductSkuForOrderVO;
import com.flyco.modules.stm.entity.StmStoreInfo;
import com.flyco.modules.stm.service.IStmOrderService;
import com.flyco.modules.stm.service.IStmStockService;
import com.flyco.modules.stm.service.IStmStoreInfoService;
import com.flyco.modules.stm.vo.StmStockVO;
import org.apache.shiro.SecurityUtils;
import com.flyco.poi.excel.ExcelImportUtil;
import com.flyco.poi.excel.def.NormalExcelConstants;
import com.flyco.poi.excel.entity.ExportParams;
import com.flyco.poi.excel.entity.ImportParams;
import com.flyco.poi.excel.view.EntityExcelView;
import com.flyco.common.system.vo.LoginUser;
import com.flyco.common.api.vo.Result;
import com.flyco.common.system.query.QueryGenerator;
import com.flyco.modules.oms.vo.OmsElemeRetailOrderPage;
import com.flyco.modules.oms.service.IOmsElemeRetailOrderService;
import com.flyco.modules.oms.service.IOmsElemeGoodsItemService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import com.flyco.common.aspect.annotation.AutoLog;

/**
 * @Description: 饿了么订单表
 * @Author: flyco
 * @Date: 2021-08-10
 * @Version: V1.0
 */
@Api(tags = "饿了么订单表")
@RestController
@RequestMapping("/f/oms/omsElemeRetailOrder")
@Slf4j
public class OmsElemeRetailOrderController {
    @Autowired
    private IOmsElemeRetailOrderService omsElemeRetailOrderService;
    @Autowired
    private IOmsElemeGoodsItemService omsElemeGoodsItemService;
    @Autowired
    private RedisUtil redisUtil;
    @Autowired
    private IStmStoreInfoService stmStoreInfoService;
    @Autowired
    private IPmsProductService pmsProductService;
    @Autowired
    private IStmOrderService omsOrderService;
    @Autowired
    private IStmStockService stmStockService;

    /**
     * 分页列表查询
     *
     * @param omsElemeRetailOrder
     * @param pageNo
     * @param pageSize
     * @param req
     * @return
     */
    @AutoLog(value = "饿了么订单表-分页列表查询")
    @ApiOperation(value = "饿了么订单表-分页列表查询", notes = "饿了么订单表-分页列表查询")
    @GetMapping(value = "/list")
    public Result<?> queryPageList(OmsElemeRetailOrder omsElemeRetailOrder,
                                   @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
                                   @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
                                   HttpServletRequest req) {
        QueryWrapper<OmsElemeRetailOrder> queryWrapper = QueryGenerator.initQueryWrapper(omsElemeRetailOrder, req.getParameterMap());
        Page<OmsElemeRetailOrder> page = new Page<OmsElemeRetailOrder>(pageNo, pageSize);
        IPage<OmsElemeRetailOrder> pageList = omsElemeRetailOrderService.page(page, queryWrapper);
        return Result.ok(pageList);
    }

    /**
     * 添加
     *
     * @param omsElemeRetailOrderPage
     * @return
     */
    @AutoLog(value = "饿了么订单表-添加")
    @ApiOperation(value = "饿了么订单表-添加", notes = "饿了么订单表-添加")
    @PostMapping(value = "/add")
    public Result<?> add(@RequestBody OmsElemeRetailOrderPage omsElemeRetailOrderPage) {
        OmsElemeRetailOrder omsElemeRetailOrder = new OmsElemeRetailOrder();
        BeanUtils.copyProperties(omsElemeRetailOrderPage, omsElemeRetailOrder);
        omsElemeRetailOrderService.save(omsElemeRetailOrder);
        return Result.ok("添加成功！");
    }

    /**
     * 编辑
     *
     * @param omsElemeRetailOrderPage
     * @return
     */
    @AutoLog(value = "饿了么订单表-编辑")
    @ApiOperation(value = "饿了么订单表-", notes = "饿了么订单表-编辑")
    @PutMapping(value = "/edit")
    public Result<?> edit(@RequestBody OmsElemeRetailOrderPage omsElemeRetailOrderPage) {
        OmsElemeRetailOrder omsElemeRetailOrder = new OmsElemeRetailOrder();
        BeanUtils.copyProperties(omsElemeRetailOrderPage, omsElemeRetailOrder);
        omsElemeRetailOrderService.updateById(omsElemeRetailOrder);
        return Result.ok("编辑成功!");
    }

    /**
     * 通过id删除
     *
     * @param id
     * @return
     */
    @AutoLog(value = "饿了么订单表-通过id删除")
    @ApiOperation(value = "饿了么订单表-通过id删除", notes = "饿了么订单表-通过id删除")
    @DeleteMapping(value = "/delete")
    public Result<?> delete(@RequestParam(name = "id", required = true) String id) {
        omsElemeRetailOrderService.delMain(id);
        return Result.ok("删除成功!");
    }

    /**
     * 批量删除
     *
     * @param ids
     * @return
     */
    @AutoLog(value = "饿了么订单表-批量删除")
    @ApiOperation(value = "饿了么订单表-批量删除", notes = "饿了么订单表-批量删除")
    @DeleteMapping(value = "/deleteBatch")
    public Result<?> deleteBatch(@RequestParam(name = "ids", required = true) String ids) {
        this.omsElemeRetailOrderService.removeByIds(Arrays.asList(ids.split(",")));
        return Result.ok("批量删除成功！");
    }

    /**
     * 通过id查询
     *
     * @param id
     * @return
     */
    @AutoLog(value = "饿了么订单表-通过id查询")
    @ApiOperation(value = "饿了么订单表-通过id查询", notes = "饿了么订单表-通过id查询")
    @GetMapping(value = "/queryById")
    public Result<?> queryById(@RequestParam(name = "id", required = true) String id) {
        OmsElemeRetailOrder omsElemeRetailOrder = omsElemeRetailOrderService.getById(id);
        return Result.ok(omsElemeRetailOrder);
    }

    //===========================以下是子表信息操作相关API====================================

    /**
     * 通过主表id查询饿了么订单明细表
     *
     * @param omsElemeGoodsItem
     * @return
     */
    @AutoLog(value = "饿了么订单明细表-通过主表id查询")
    @ApiOperation(value = "饿了么订单明细表-通过主表id查询", notes = "饿了么订单明细表-通过主表id查询")
    @GetMapping(value = "/listOmsElemeGoodsItemByMainId")
    public Result<?> listOmsElemeGoodsItemByMainId(OmsElemeGoodsItem omsElemeGoodsItem,
                                                   @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
                                                   @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
                                                   HttpServletRequest req) {
        if (omsElemeGoodsItem.getOrderId() != null) {
            QueryWrapper<OmsElemeGoodsItem> queryWrapper = QueryGenerator.initQueryWrapper(omsElemeGoodsItem, req.getParameterMap());
            Page<OmsElemeGoodsItem> page = new Page<OmsElemeGoodsItem>(pageNo, pageSize);
            IPage<OmsElemeGoodsItem> pageList = omsElemeGoodsItemService.page(page, queryWrapper);
            return Result.ok(pageList);
        } else {
            return Result.ok();
        }
    }

    /**
     * 添加饿了么订单明细表
     *
     * @param omsElemeGoodsItem
     * @return
     */
    @AutoLog(value = "饿了么订单明细表-添加")
    @ApiOperation(value = "饿了么订单明细表-添加", notes = "饿了么订单明细表-添加")
    @PostMapping(value = "/addOmsElemeGoodsItem")
    public Result<?> addOmsElemeGoodsItem(@RequestBody OmsElemeGoodsItem omsElemeGoodsItem) {
        omsElemeGoodsItemService.save(omsElemeGoodsItem);
        return Result.ok("添加饿了么订单明细表成功！");
    }

    /**
     * 编辑饿了么订单明细表
     *
     * @param omsElemeGoodsItem
     * @return
     */
    @AutoLog(value = "饿了么订单明细表-编辑")
    @ApiOperation(value = "饿了么订单明细表-编辑", notes = "饿了么订单明细表-编辑")
    @PutMapping("/editOmsElemeGoodsItem")
    public Result<?> editOmsElemeGoodsItem(@RequestBody OmsElemeGoodsItem omsElemeGoodsItem) {
        omsElemeGoodsItemService.updateById(omsElemeGoodsItem);
        return Result.ok("编辑饿了么订单明细表成功！");
    }

    /**
     * 通过id删除饿了么订单明细表
     *
     * @param id
     * @return
     */
    @AutoLog(value = "饿了么订单明细表-通过id删除")
    @ApiOperation(value = "饿了么订单明细表-通过id删除", notes = "饿了么订单明细表-通过id删除")
    @DeleteMapping(value = "/deleteOmsElemeGoodsItem")
    public Result<?> deleteOmsElemeGoodsItem(@RequestParam(name = "id", required = true) String id) {
        omsElemeGoodsItemService.removeById(id);
        return Result.ok("删除饿了么订单明细表成功！");
    }

    /**
     * 批量删除饿了么订单明细表
     *
     * @param ids
     * @return
     */
    @AutoLog(value = "饿了么订单明细表-批量删除")
    @ApiOperation(value = "饿了么订单明细表-批量删除", notes = "饿了么订单明细表-批量删除")
    @DeleteMapping(value = "/deleteBatchOmsElemeGoodsItem")
    public Result<?> deleteBatchOmsElemeGoodsItem(@RequestParam(name = "ids", required = true) String ids) {
        if (ids == null || "".equals(ids.trim())) {
            return Result.error("参数不识别！");
        }
        this.omsElemeGoodsItemService.removeByIds(Arrays.asList(ids.split(",")));
        return Result.ok("批量删除成功！");

    }


    /**
     * 导出excel
     *
     * @param request
     * @param omsElemeRetailOrder
     */
    @RequestMapping(value = "/exportXls")
    public ModelAndView exportXls(HttpServletRequest request, OmsElemeRetailOrder omsElemeRetailOrder) {
        // Step.1 组装查询条件
        QueryWrapper<OmsElemeRetailOrder> queryWrapper = QueryGenerator.initQueryWrapper(omsElemeRetailOrder, request.getParameterMap());
        LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();

        //Step.2 获取导出数据
        List<OmsElemeRetailOrderPage> pageList = new ArrayList<OmsElemeRetailOrderPage>();
        List<OmsElemeRetailOrder> omsElemeRetailOrderList = omsElemeRetailOrderService.list(queryWrapper);
        for (OmsElemeRetailOrder temp : omsElemeRetailOrderList) {
            OmsElemeRetailOrderPage vo = new OmsElemeRetailOrderPage();
            BeanUtils.copyProperties(temp, vo);
            List<OmsElemeGoodsItem> omsElemeGoodsItemList = omsElemeGoodsItemService.selectByMainId(temp.getId());
            vo.setOmsElemeGoodsItemList(omsElemeGoodsItemList);
            pageList.add(vo);
        }
        //Step.3 调用AutoPoi导出Excel
        ModelAndView mv = new ModelAndView(new EntityExcelView());
        mv.addObject(NormalExcelConstants.FILE_NAME, "饿了么订单表");
        mv.addObject(NormalExcelConstants.CLASS, OmsElemeRetailOrderPage.class);
        mv.addObject(NormalExcelConstants.PARAMS, new ExportParams("饿了么订单表数据", "导出人:" + sysUser.getRealname(), "饿了么订单表"));
        mv.addObject(NormalExcelConstants.DATA_LIST, pageList);
        return mv;
    }

    /**
     * 通过excel导入数据
     *
     * @param request
     * @param response
     * @return
     */
    @RequestMapping(value = "/importExcel", method = RequestMethod.POST)
    public Result<?> importExcel(HttpServletRequest request, HttpServletResponse response) {
        StringBuilder errMsg = new StringBuilder("");
        MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
        Map<String, MultipartFile> fileMap = multipartRequest.getFileMap();
        for (Map.Entry<String, MultipartFile> entity : fileMap.entrySet()) {
            MultipartFile file = entity.getValue();// 获取上传文件对象
            ImportParams params = new ImportParams();
            params.setTitleRows(2);
            params.setHeadRows(1);
            params.setNeedSave(true);
            try {
                List<OmsElemeRetailOrderPage> list = ExcelImportUtil.importExcel(file.getInputStream(), OmsElemeRetailOrderPage.class, params);
                Set<Long> shopIds = list.stream().map(r -> r.getShopId()).collect(Collectors.toSet());
                List<String> elemeIds = list.stream().map(r->r.getElemeId()).collect(Collectors.toList());
                LambdaQueryWrapper<OmsElemeRetailOrder> elemeOrderQueryWrapper = new LambdaQueryWrapper<>();
                elemeOrderQueryWrapper.in(OmsElemeRetailOrder::getElemeId, elemeIds);
                List<OmsElemeRetailOrder> elemeRetailOrders = omsElemeRetailOrderService.list(elemeOrderQueryWrapper);
                if (elemeRetailOrders.size() > 0) {
                    errMsg.append("存在重复导入单据，单号：");
                    List<OmsElemeRetailOrderPage> repeatOrder = new ArrayList<>();
                    elemeRetailOrders.forEach(o->{
                        list.stream().filter(r->Objects.equals(r.getElemeId(), o.getElemeId())).forEach(r->{
                            errMsg.append(r.getElemeId());
                            errMsg.append(",");
                            repeatOrder.add(r);
                        });
                    });
                    if (repeatOrder.size() > 0 ) {
                        list.removeAll(repeatOrder);
                    }
                }

                LambdaQueryWrapper<StmStoreInfo> storeQueryWrapper = new LambdaQueryWrapper<>();
                storeQueryWrapper.in(StmStoreInfo::getElemeCode, shopIds);
				List<StmStoreInfo> storeInfos = stmStoreInfoService.list(storeQueryWrapper);
				Map<String, StmStoreInfo> storeInfoMap = storeInfos.stream().collect(Collectors.toMap(StmStoreInfo:: getElemeCode, Function.identity(), (key1, key2) -> key2));

                for (OmsElemeRetailOrderPage page : list) {
					page.setId(generateOrderSn());
                    OmsElemeRetailOrder po = new OmsElemeRetailOrder();
                    BeanUtils.copyProperties(page, po);
                    if (storeInfoMap.containsKey(String.valueOf(po.getShopId())) ) {
                        Long storeId = storeInfoMap.get(String.valueOf(po.getShopId())).getStoreId();
						OmsOrderPage orderPage = generateStoreOrder(page, storeId);
                        OmsOrder omsOrder = new OmsOrder();
                        BeanUtils.copyProperties(orderPage, omsOrder);
                        omsOrderService.saveMain(omsOrder, orderPage.getOmsOrderItemList(), orderPage.getOmsOrderInvoiceList());
						omsElemeRetailOrderService.saveMain(po, page.getOmsElemeGoodsItemList());
                        List<StmStockVO> stockVOS = generateStockRecord(orderPage);
                        String changeReason = "饿了么销售出库";
                        stmStockService.stockInOut(stockVOS, storeId, StockConstant.STOCK_OUT, StockConstant.STOCK_OUT_TYPE_SALE, StockConstant.RECEIPT_TYPE_SALE, page.getId(), changeReason );
					}
                }
                if (list.size() > 0)
                    errMsg.append("文件导入成功！数据行数:" + list.size());
                return Result.ok(errMsg.toString());
            } catch (Exception e) {
                log.error(e.getMessage(), e);
                return Result.error("文件导入失败:" + e.getMessage());
            } finally {
                try {
                    file.getInputStream().close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        errMsg.append("文件导入失败！");
        return Result.ok(errMsg.toString());
    }

    private List<StmStockVO> generateStockRecord(OmsOrderPage orderPage) {
        List<StmStockVO> outStockVOList = new ArrayList<>();
        orderPage.getOmsOrderItemList().forEach(item->{
            StmStockVO vo = BeanUtils.instantiateClass(StmStockVO.class);
            vo.setProductId(item.getProductId());
            vo.setProductSn(item.getProductSn());
            vo.setStockType(StockConstant.STOCK_TYPE_GOODS);
            vo.setProductQty(item.getProductQuantity());
            outStockVOList.add(vo);
        });
        return outStockVOList;
    }

    private OmsOrderPage generateStoreOrder(OmsElemeRetailOrderPage page, Long storeId) {
        OmsOrderPage order = new OmsOrderPage();
        order.setId(page.getId());
        order.setStoreId(storeId);
        order.setOrderSn(page.getId());
        order.setMemberId(1L);
        order.setCreateTime(page.getCreatedAt());
        order.setTotalAmount(page.getOriginalPrice());
        order.setPayAmount(page.getTotalPrice());
        order.setEffectiveAmount(page.getIncome());
        //order.setDiscountAmount(page.getServiceFee());
        order.setPayType("unionPay");
        order.setSourceType("admin");
        order.setSourceSystem("third");
        order.setStatus(3);
        order.setProductStatus(5);
        order.setPayStatus(4);
        order.setReceiverName("饿了么默认用户");
        order.setReceiverPhone("10000000000");
        order.setConfirmStatus(1);
        List<OmsOrderItem> omsOrderItemList = new ArrayList<>();
        List<OmsOrderInvoice> omsOrderInvoiceList = new ArrayList<>();
		OmsOrderInvoice orderInvoice = new OmsOrderInvoice();
		orderInvoice.setOrderId(page.getId());
		orderInvoice.setInvoiceType("0");
		orderInvoice.setInvoiceTitle("个人");
		omsOrderInvoiceList.add(orderInvoice);
		order.setOmsOrderInvoiceList(omsOrderInvoiceList);
		List<String> barCodes = page.getOmsElemeGoodsItemList().stream().map(r-> r.getBarCode()).collect(Collectors.toList());
        List<PmsProductSkuForOrderVO> skuForOrderVOS = pmsProductService.getProductSkuForOrderList(storeId, barCodes);
        Map<String, PmsProductSkuForOrderVO> skuCodeMap = skuForOrderVOS.stream().collect(Collectors.toMap(PmsProductSkuForOrderVO::getSkuCode, t -> t));

        for (OmsElemeGoodsItem item : page.getOmsElemeGoodsItemList()) {
            OmsOrderItem orderItem = new OmsOrderItem();
            orderItem.setOrderId(page.getId());
            orderItem.setOrderSn(page.getId());
            orderItem.setProductSkuCode(item.getBarCode());
            //
            orderItem.setProductQuantity(item.getQty());
            if (item.getPreferentialQty() >0) {
                orderItem.setProductPrice(item.getAfterPreferentialPrice());
            } else {
                orderItem.setProductPrice(item.getBeforePreferentialPrice());
            }
            orderItem.setTotalPromotionAmount(new BigDecimal(isNumeric(item.getShopPart())? item.getShopPart() : "0" ));
            orderItem.setTotalCouponAmount(new BigDecimal(isNumeric(item.getShopCouponAmount()) ? item.getShopCouponAmount() : "0" ));
            orderItem.setTotalRealAmount(new BigDecimal(isNumeric(item.getShopRedbagAmount()) ? item.getShopRedbagAmount() : "0" ));
            orderItem.setTotalIntegrationAmount(new BigDecimal(isNumeric(item.getShopCashAmount()) ? item.getShopCashAmount() : "0" ));
            orderItem.setProductName(item.getProductName());
            if (skuCodeMap.containsKey(item.getBarCode())) {
                PmsProductSkuForOrderVO vo = skuCodeMap.get(item.getBarCode());
                orderItem.setProductId(vo.getId());
                orderItem.setProductPic(vo.getPic());
                orderItem.setProductBrand(vo.getBrandName());
                orderItem.setProductSn(vo.getProductSn());
                orderItem.setProductSkuId(vo.getSkuId());
                orderItem.setProductCategoryId(vo.getProductCategoryId());
            }
            omsOrderItemList.add(orderItem);
        }
		order.setOmsOrderItemList(omsOrderItemList);
        return order;
    }

    public static boolean isNumeric(String str) {
        return str.matches("-?[0-9]+.？[0-9]*");
    }

    /**
     * 生成18位订单编号:8位日期+2位平台号码+2位支付方式+6位以上自增id
     */
    private String generateOrderSn() {
        String date = new SimpleDateFormat("yyyyMMddHH").format(new Date());
        String key = "portal:orderId:" + date;
        long seq = redisUtil.incr(key, 1);
        if (seq == 1L) {
            seq = redisUtil.incr(key, (long) (Math.random() * 500000));
            redisUtil.expire(key, 3600 * 2L);
        }
        return "" + IdUtil.genId("yyMMddHH{s}{s}{s}{s}{s}{r}{s}7", seq, 6);
    }


}
